Fork me on GitHub

Fair-Play

题目

The quick brown fox jumps over the lazy dog!
​ ihxo{smzdodcikmodcismzd}

题目链接

http://www.shiyanbar.com/ctf/1852

题解

The quick brown fox jumps over the lazy dog!
​ ihxo{smzdodcikmodcismzd}

输入密钥:Thequickbrownfoxjumpsoverthelazydog
请输入密文:ihxo{smzdodcikmodcismzd}
解密后所得到的明文是:CTFXKMPAAFZBRCOIZBKMPAAB

playfair密码

playfair密码(英文:Playfair cipher 或 Playfair square)是一种替换密码,1854年由查尔斯·惠斯通(Charles Wheatstone)的英国人发明。

题目提示是Fair-Play,得知是playfair密码。

首先playfair的加密过程用到一个5x5的字母矩阵,容纳26个字母,其中i和j挤到一个格子里,字母填写顺序取

决于密钥,The quick brown fox jumps over the lazy dog!

将空格去掉,然后填入矩阵里,重复出现的字母只填一次

填完后如下表:
t h e q u
i/j c k b r
o w n f x
m p s v l
a z y d g
填完密钥出现的字母后,若还有空余,就填字母表中剩余的字母(按字母表顺序)

加密过程:把明文按两个字母一组分组,比如hello就分成he,lx,lo

相邻字母相同的情况下,中间加个填充字母x(有时候是q),若最后一个字母没组员,也加个填充字母。

加密规则

​ 两明文字母m1,m2同行:密文字母c1,c2在它们右边,同行循环,比如hu加密后是et;

​ m1,m2同列:c1,c2在它们下边,同列循环,hz加密后是ch;

​ m1,m2不同行列:c1,c2是m1,m2 组成的长方形的另两个顶点,顺序是c1与m1同行,c2与m2同行,cd加密后是bz;

解密规则

1 若c1 c2在同一行,对应明文p1 p2分别是紧靠c1 c2 左端的字母。其中最后一列被看做是第一列的左方。

2 若c1 c2在同一列,对应明文p1 p2分别是紧靠c1 c2 上方的字母。其中最后一行被看做是第一行的上方。

3 若c1 c2不在同一行,不在同一列,则p1 p2是由c1 c2确定的矩形的其他两角的字母。

其实就是反其道而行之。

附上网上找的一个解密程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
#include<iostream>
#include<cstring>
using namespace std;
void decrypt();//解密函数
void encrypt();//加密函数
int main()
{
cout<<"****************************Playfair算法加解密程序***************************"<<endl;
cout<<"*********************************欢迎使用本程序******************************"<<endl<<endl;
int n=0;
for(;n!=3;)
{
cout<<"选择你所需要的操作:"<<endl;
cout<<"1------为字符串加密;"<<endl;
cout<<"2------为字符串解密;"<<endl;
cout<<"3------结束程序。"<<endl;
cout<<"选择操作:";
cin>>n;
if(n<1||n>3)cout<<"无该项操作,请重来:"<<endl;
switch(n)
{
case 1:encrypt();
cout<<"-------------------------------------------------------------------"<<endl;
cout<<"--------------------------加密结束---------------------------------"<<endl<<endl;
break;
case 2:decrypt();
cout<<"-------------------------------------------------------------------"<<endl;
cout<<"--------------------------解密结束---------------------------------"<<endl<<endl;
break;
case 3:cout<<"*******************************程序结束******************************"<<endl;
break;
default:break;
}
}
system("pause");
return 0;
}
///////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////
//加密算法
void encrypt()
{
const int N=100;
char letters[26]="ABCDEFGHIKLMNOPQRSTUVWXYZ";//用于填充矩阵
int flag[25]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};//标记字母是否已在矩阵中,与letters数组对应
char ch[5][5];//5X5矩阵
char ch1[N];//密钥
char ch2[N];//明文
//char ch3[N];//密文
char ch4;//无关字符
int len='a'-'A';
cout<<"输入密钥:";
cin>>ch1;
for(int i=0;i<strlen(ch1);i++)//把所输入的密钥转化为大写字母
{
if(ch1[i]>='a')
ch1[i]=ch1[i]-len;
}
cout<<"输入无关字符:";
cin>>ch4;
if(ch4>='a')ch4=ch4-len;
for(int i=0;i<strlen(ch1);i++)//把密钥中的J都变为I,因为在算法中I与J是等价的
{
if(ch1[i]=='J')ch1[i]='I';
}
int i=0,j=0;
for(int k=0;k<strlen(ch1);k++)//把密钥中的字母填入到矩阵中,并把该字母标记为已用
{
for(int t=0;t<25;t++)
{
if(ch1[k]==letters[t]&&flag[t]==0)
{
ch[i][j]=letters[t];
flag[t]=1;
if(j<4)j++;
else {i++;j=0;}
}
}
}
for(int k=0;k<25;k++)//按字母表顺序把未用字母依次填入到矩阵中
{
if(flag[k]==0)
{
ch[i][j]=letters[k];
flag[k]=1;
if(j<4)j++;
else{i++;j=0;}
}
}
////////////////////////////////////////矩阵生成完毕/////////////////////////////////////////////////////
for(int k=0;k<5;k++)
{
for(int t=0;t<5;t++)
cout<<ch[k][t]<<" ";
cout<<endl;
}
cout<<"请输入明文:";
cin>>ch2;
for(int k=0;k<strlen(ch2);k++)//把所输入的明文转化为大写字母
{
if(ch2[k]>='a')
ch2[k]=ch2[k]-len;
}
for(int k=0;k<strlen(ch2);k++)//把明文中的J都变为I,因为在算法中I与J是等价的
{
if(ch2[k]=='J')ch2[k]='I';
}
//cout<<ch2<<endl;
for(int k=0;k<strlen(ch2);k+=2)//为明文添加必要的无关字符以防止同一组的两个字符相同
{
if(ch2[k]==ch2[k+1])
{
for(int t=strlen(ch2);t>k;t--)
ch2[t+1]=ch2[t];
ch2[k+1]=ch4;
}
}
if(strlen(ch2)%2!=0){ch2[strlen(ch2)+1]=ch2[strlen(ch2)];ch2[strlen
(ch2)]=ch4;}//若明文有奇数个字符,则添加一个无关字符以凑够偶数个
cout<<"经过处理后的明文为:"<<ch2<<" 其最终长度为:"<<strlen(ch2)
<<endl;
/////////////////////////////////////////////明文输入并整理完毕/////////////////////////////////////////////////////
for(int k=0;k<strlen(ch2);k+=2)
{
int m1,m2,n1,n2;
for(m1=0;m1<=4;m1++)
{
for(n1=0;n1<=4;n1++)
{
if(ch2[k]==ch[m1][n1])break;
}
if(ch2[k]==ch[m1][n1])break;
}
for(m2=0;m2<=4;m2++)
{
for(n2=0;n2<=4;n2++)
{
if(ch2[k+1]==ch[m2][n2])break;
}
if(ch2[k+1]==ch[m2][n2])break;
}
m1=m1%5;
m2=m2%5;
if(n1>4){n1=n1%5;m1=m1+1;}
if(n2>4){n2=n2%5;m2=m2+1;}
if(m1==m2)
{
ch2[k]=ch[m1][(n1+1)%5];
ch2[k+1]=ch[m2][(n2+1)%5];
}
else
{
if(n1==n2)
{
ch2[k]=ch[(m1+1)%5][n1];
ch2[k+1]=ch[(m2+1)%5][n2];
}
else
{
ch2[k]=ch[m1][n2];
ch2[k+1]=ch[m2][n1];
}
}
}
cout<<"加密后所得到的密文是:"<<ch2<<endl;
}
///////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////
//解密算法
void decrypt()
{
const int N=100;
char letters[26]="ABCDEFGHIKLMNOPQRSTUVWXYZ";//用于填充矩阵
int flag[25]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};//标记字母是否已在矩阵中,与letters数组对应
char ch[5][5];//5X5矩阵
char ch1[N];//密钥
char ch2[N];//密文
int len='a'-'A';
cout<<"输入密钥:";
cin>>ch1;
for(int i=0;i<strlen(ch1);i++)//把所输入的密钥转化为大写字母
{
if(ch1[i]>='a')
ch1[i]=ch1[i]-len;
}
for(int i=0;i<strlen(ch1);i++)//把密钥中的J都变为I,因为在算法中I与J是等价的
{
if(ch1[i]=='J')ch1[i]='I';
}
int i=0,j=0;
for(int k=0;k<strlen(ch1);k++)//把密钥中的字母填入到矩阵中,并把该字母标记为已用
{
for(int t=0;t<25;t++)
{
if(ch1[k]==letters[t]&&flag[t]==0)
{
ch[i][j]=letters[t];
flag[t]=1;
if(j<4)j++;
else {i++;j=0;}
}
}
}
for(int k=0;k<25;k++)//按字母表顺序把未用字母依次填入到矩阵中
{
if(flag[k]==0)
{
ch[i][j]=letters[k];
flag[k]=1;
if(j<4)j++;
else{i++;j=0;}
}
}
////////////////////////////////////////矩阵生成完毕/////////////////////////////////////////////////////
int f=0;
do{
cout<<"请输入密文:";
cin>>ch2;
for(int k=0;k<strlen(ch2);k++)//把所输入的密文转化为大写字母
{
if(ch2[k]>='a')
ch2[k]=ch2[k]-len;
}
for(int k=0;k<strlen(ch2);k++)//把密文中的J都变为I,因为在算法中I与J是等价的
{
if(ch2[k]=='J')ch2[k]='I';
}
for(int k=0;k<strlen(ch2);k+=2)
{
if(ch2[k]==ch2[k+1])
{
cout<<"该字符串并不是使用Playfair算法加密后可以得到的形式。"<<endl;
f=1;
break;
}else f=2;
}
if(f==1)continue;
if(strlen(ch2)%2!=0){cout<<"该字符串并不是使用Playfair算法加密后可以得到的形式。"<<endl;f=1;}
else f=2;
}while(f==1);
///////////////////////////////////////////////////////////////////////////////
//////////////////////////////
/////////////解密开始
for(int k=0;k<strlen(ch2);k+=2)
{
int m1,m2,n1,n2;
for(m1=0;m1<=4;m1++)
{
for(n1=0;n1<=4;n1++)
{
if(ch2[k]==ch[m1][n1])break;
}
if(ch2[k]==ch[m1][n1])break;
}
for(m2=0;m2<=4;m2++)
{
for(n2=0;n2<=4;n2++)
{
if(ch2[k+1]==ch[m2][n2])break;
}
if(ch2[k+1]==ch[m2][n2])break;
}
m1=m1%5;
m2=m2%5;
if(n1>4){n1=n1%5;m1=m1+1;}
if(n2>4){n2=n2%5;m2=m2+1;}
if(m1==m2)
{
ch2[k]=ch[m1][(n1+4)%5];
ch2[k+1]=ch[m2][(n2+4)%5];
}
else
{
if(n1==n2)
{
ch2[k]=ch[(m1+4)%5][n1];
ch2[k+1]=ch[(m2+4)%5][n2];
}
else
{
ch2[k]=ch[m1][n2];
ch2[k+1]=ch[m2][n1];
}
}
}
cout<<"解密后所得到的明文是:"<<ch2<<endl;
}
-------------本文结束感谢您的阅读-------------